iT邦幫忙

2023 iThome 鐵人賽

DAY 22
0
SideProject30

Hugo your Blog and Host your Podcast. 系列 第 22

AWS Lambda / Lambda is your severless solution.

  • 分享至 

  • xImage
  •  

這段關係,都是 Lambda 在默默付出

  • 如果你沒有仔細看 Big Apple 大哥的指示 可能會錯過關於 images 的限制
    https://ithelp.ithome.com.tw/upload/images/20231007/20152944AmiPVzV4yM.png
  • 這邊我們先默認大家都有正常的 .jpg, .png 只是大小不一定如要求是方正的,如果是從本機手動進行,每次都會花費蠢蠢的重複時間
  • 這時,我們就可以使用 Lambda 作為小幫手,讓他幫我們自動調整圖片大小,並且放到正確的位置

該怎麼做

  • 在 AWS lambda 選擇 Create function, 按照圖示進行,記得 Runtime 選擇 Provide your own bootstrap on Amazon Linux 2 (近期 AWS 會將較低版本的 Runtime 逐步淘汰,如 Golang 1.x...,所以要選用這個 Runtime)
    https://ithelp.ithome.com.tw/upload/images/20231007/20152944dvLXuxzssv.png
  • 作者是 Big Apple 的擁護者,後面 build 的時候也會以 Mac 為考量,所以 Architectures 選擇 arm64
  • 後面的 role 可以繼續使用給予 github actions 的 IAM role ,因為同要都只需要對 S3 進行操作
  • 在這邊操作 Add trigger ,是指這個程式不需要被手動驅動,而是會被我們設定好的某個事件種類所觸發,這邊我們選擇 S3,如圖,並把 Prefix 限定在 images/,這樣就不會把其他上傳的檔案也觸發到(也可以限定在其他你想要的位置)
    https://ithelp.ithome.com.tw/upload/images/20231007/20152944XdqOXWvCmT.png
  • 在 Configuration/ General configuration/ Timeout 設定為 1 分鐘,避免 Lambda 事情還沒做完就被強制關閉
    https://ithelp.ithome.com.tw/upload/images/20231007/20152944UTzcsfwwet.png
  • 假設各位都是 Gopher, 可以使用我醜醜的 code 作為 lambda
package main

import (
	"bytes"
	"context"
	"fmt"
	"image"
	"image/jpeg"
	"io"
	"strings"

	"github.com/aws/aws-lambda-go/events"
	"github.com/aws/aws-lambda-go/lambda"
	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/service/s3"
	"github.com/disintegration/imaging"
)

func main() {
	lambda.Start(handler)
}

func handler(ctx context.Context, s3Event events.S3Event) error {
	sess, err := session.NewSession(&aws.Config{
		// Tokyo region is ap-northeast-1
		Region: aws.String("ap-northeast-1")},
	)
	if err != nil {
		// check error, lambda logs also show up in cloudwatch
		fmt.Println("message: error = ", err.Error())
		return err
	}
	svc := s3.New(sess)
	fmt.Println("message: get session")
	// only deal with one file at a time
	object := s3Event.Records[0].S3.Object

	// key is the file name with all prefix
	key := object.Key
	// bucket is the bucket name
	bucket := "{Your Bucket Name}"
	// check the file key
	fmt.Println("message: key = ", key)
	resp, err := svc.GetObject(&s3.GetObjectInput{
		Bucket: aws.String(bucket),
		Key:    aws.String(key),
	})
	if err != nil {
		fmt.Println("message: error = ", err.Error())
		return err
	}
	defer resp.Body.Close()

	content, err := io.ReadAll(resp.Body)
	if err != nil {
		fmt.Println("message: error = ", err.Error())
		return err
	}

	img, _, err := image.Decode(bytes.NewReader(content))
	if err != nil {
		fmt.Println("message: error = ", err.Error())
		return err
	}

	resized := imaging.Resize(img, 3000, 3000, imaging.Lanczos)

	buf := new(bytes.Buffer)
	err = jpeg.Encode(buf, resized, nil)
	if err != nil {
		fmt.Println("message: error = ", err.Error())
		return err
	}
	// get the file name with prefix
	keyPath := strings.Split(key, "/")
	imageName := keyPath[len(keyPath)-1]
	// put the new resized image to the another folder, avoid infinite loop
	newKey := "/podcast/images/" + imageName

	_, err = svc.PutObject(&s3.PutObjectInput{
		Bucket:      aws.String(bucket),
		Key:         aws.String(newKey),
		ContentType: aws.String("image/jpeg"),
		Body:        bytes.NewReader(buf.Bytes()),
	})
	if err != nil {
		fmt.Println("message: error = ", err.Error())
		return err
	}

	fmt.Println("message: success")
	return nil
}
  • 並使用如下指定,把 lambda build 出來
 GOOS=linux GOARCH=arm64 CGO_ENABLED=0 go build -o bootstrap -tags lambda.norpc main.go
  • 再使用如下指令,把 lambda zip 起來
zip myFunction.zip bootstrap
  • 在 Lambda Code/ Code source 選擇 Upload from/ .zip file,並且上傳剛剛的 myFunction.zip 檔案
  • 這樣每當有圖片上傳到 images/ 以下的位置,就會觸發 lambda,並且把圖片 resize 到 3000x3000 的大小,並且放到 podcast/images/ 以下的位置,這邊的大小就是 Apple 老大哥所要求的了
  • 答拉~

其他延伸

  • 編寫 Lambda 時,可以注意有各種觸發的 Event 可以選擇,你也可以自訂自己的 struct,只要是你預期的觸發方式就好,不一定都需要從 aws-lambda-go/events package 中選擇
  • 在 build, zip 的時候,注意各種設定與環境,如果 Lambda 不如預期,也可以從 Monitor/ Logs 中去看看發生了什麼事,所以建議 Lambda 中可以多一些 message 幫助 debug
  • lambda 便宜所以可以多玩玩,但因為上傳的是已經 build 好的 binary,所以最好也把原始碼放在 github 上,這樣可以方便管理與維護
  • 這支 Lambda 只負責把圖片壓成 3000x3000,不負責 crop 或修圖喔

外出取材

  • 愛丁堡是個小小的城市,可以參加各種有趣的 Tour,會有不同的體驗與了解,參加 Tour 才知道目前住宿的青旅前身是個監獄,也參觀了古老的橋下穴居與墓園探險,很值得參加~
    https://ithelp.ithome.com.tw/upload/images/20231007/20152944qingXdoj97.jpg
    https://ithelp.ithome.com.tw/upload/images/20231007/20152944FkDvivjZAE.jpg

上一篇
AWS Cloudfront Invalidation / Forget-me-right-now.
下一篇
JSON init/ Prepare well for Lambda.
系列文
Hugo your Blog and Host your Podcast. 30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言